
#include "OMPInterface.h"


OMPInterface::OMPInterface(){
	fwdTable = new ParallelFwd3();
	//memset(interfaces, -1, sizeof(int)*MAX_NUM_INTERFACES);
	for (int j=0; j<MAX_NUM_INTERFACES; j++){
		interfaces[j] = -1;
	}
}

OMPInterface::~OMPInterface(){
	 delete fwdTable;
}

void OMPInterface::processEvent(PubPkt* pkt, Outbox &outbox){

	cout << "Subscription manager: OCM: start processing..." << endl;
	OMPMessage *message = translate(pkt);

	OMPOutbox *OMPoutbox = new OMPOutbox;
	OMPoutbox->message = message;
	fwdTable->processMessage(OMPoutbox);
	outbox.pkts.insert(pkt);
	//std::set<PubPkt*> pktSet;
	//pktSet.insert(pkt);

	for (std::set<int>::iterator it = OMPoutbox->outgoingInterfaces.begin(); it != OMPoutbox->outgoingInterfaces.end(); it++){
		outbox.clients.insert(interfaces[*it]);
	}
	//outbox.clients = OMPoutbox->outgoingInterfaces;
	//std::set<int> clientsMatched = OMPoutbox->outgoingInterfaces;
	//Outbox* outbox = new Outbox(clientsMatched, pktSet);
	outbox.setNs(OMPoutbox->ns);
	outbox.setWs(OMPoutbox->ws);
	outbox.setLastPercentage(OMPoutbox->last);
	cout << "Subscription manager: OCM: forwarding executed." << endl;
	delete OMPoutbox;
	//return outbox;
}

void OMPInterface::installSubscription(Inbox* inbox){

	cout << "Subscription manager: OCM: start installing subscription..." << endl;
	/*** UNICO MODO PER RESETTARE LA table di OMP ***/
//	delete fwdTable;
	fwdTable = new ParallelFwd3();
	/************************************************/
	int interface;
/*	int clientId = inbox->getClient();
	boost::unordered_map<int, InnerInterface>::iterator itInt = interfacesMap.find(clientId);
	if (itInt != interfacesMap.end()){
		interface = itInt->second.interface;
	} else {
*/	bool found = false;
	for (int j=0; j<MAX_NUM_INTERFACES; j++){
		if (interfaces[j] == inbox->getClient()){
			interface = j;
			found = true;
			break;
		}
	}
	if (!found){
		int i = 0;
		while (interfaces[i] >= 0 && i<MAX_NUM_INTERFACES) i++;
		if (i == MAX_NUM_INTERFACES) {
			cout << "Subscription manager: OCM: subscription cannot be installed: limit reached." << endl;
			return;
		}
		interfaces[i] = inbox->getClient();
		interface = i;
	}
//	}
	boost::unordered_map<int, std::set<OMPFilter *> >::iterator it = OMPForwardingMap.find(interface);
	if (it != OMPForwardingMap.end()){
		OMPFilter *filter = translate(inbox->getSubPkt());
		it->second.insert(filter);
	} else {
		OMPFilter *filter = translate(inbox->getSubPkt());
		std::set<OMPFilter*> filterSet;
		filterSet.insert(filter);
		OMPForwardingMap.insert(make_pair(interface, filterSet));
	}
	cout << "Subscription manager: OCM: subscription installed." << endl;
	cout << "Subscription manager: OCM: start updating forwarding table..." << endl;
	for (boost::unordered_map<int, std::set<OMPFilter *> >::iterator it = OMPForwardingMap.begin(); it != OMPForwardingMap.end(); it++) {
		  fwdTable->ifConfig(it->first, it->second);
		//  cout << "interfaccia aggiunta" << endl;
	}
	fwdTable->consolidate();
	cout << "Subscription manager: OCM: forwarding table updated." << endl;
}

void OMPInterface::deleteSubscription(Inbox* inbox){

}


OMPFilter* OMPInterface::translate(BackSubPkt* pkt){
	OMPFilter *ompFilter = new OMPFilter();

	ompFilter->constraints[0].name[0] = 't';
	ompFilter->constraints[0].name[1] = 'y';
	ompFilter->constraints[0].name[2] = 'p';
	ompFilter->constraints[0].name[3] = 'e';
	ompFilter->constraints[0].name[4] = '\0';
	ompFilter->constraints[0].op = EQ;
	ompFilter->constraints[0].value.type = INT;
	ompFilter->constraints[0].value.intVal = pkt->getEventType();

	ompFilter->numConstraints = pkt->getConstraintsNum()+1;
	for (int i=0; i<pkt->getConstraintsNum(); i++){
		int j=0;
		while (pkt->getConstraint(i).name[j] != '\0'){
			ompFilter->constraints[i+1].name[j] = pkt->getConstraint(i).name[j];
			j++;
		}
		ompFilter->constraints[i+1].name[j] = '\0';
		ompFilter->constraints[i+1].op = pkt->getConstraint(i).op;
		if (pkt->getConstraint(i).type == INT){
			ompFilter->constraints[i+1].value.type = INT;
			ompFilter->constraints[i+1].value.intVal = pkt->getConstraint(i).intVal;
		} else
		if (pkt->getConstraint(i).type == FLOAT){
			// NON PREVISTO
		} else
		if (pkt->getConstraint(i).type == BOOL){
			// NON PREVISTO
		} else
		if (pkt->getConstraint(i).type == STRING){
			ompFilter->constraints[i+1].value.type = STRING;
			int k=0;
			while (pkt->getConstraint(i).stringVal[k] != '\0'){
				ompFilter->constraints[i+1].value.stringVal[k] = pkt->getConstraint(i).stringVal[k];
				k++;
			}
			ompFilter->constraints[i+1].value.stringVal[k] = '\0';
		}
	}
	ompFilter->window = pkt->getWindow();
	if (pkt->getOccurrence() == LAST){
		ompFilter->occurrence = 1;
	} else {
		ompFilter->occurrence = 0;
	}
	cout << "Subscription manager: OCM: subscription translated." << endl;
	return ompFilter;
}


OMPMessage* OMPInterface::translate(PubPkt* pkt){
	OMPMessage *ompMessage = new OMPMessage();

	ompMessage->attributes[0].name[0] = 't';
	ompMessage->attributes[0].name[1] = 'y';
	ompMessage->attributes[0].name[2] = 'p';
	ompMessage->attributes[0].name[3] = 'e';
	ompMessage->attributes[0].name[4] = '\0';
	ompMessage->attributes[0].value.type = INT;
	ompMessage->attributes[0].value.intVal = pkt->getEventType();

	ompMessage->numAttributes = pkt->getAttributesNum()+1;
	for (int i=0; i<pkt->getAttributesNum(); i++){
		int j=0;
		while (pkt->getAttribute(i).name[j] != '\0'){
			ompMessage->attributes[i+1].name[j] = pkt->getAttribute(i).name[j];
			j++;
		}
		ompMessage->attributes[i+1].name[j] = '\0';
		if (pkt->getAttribute(i).type == INT)
		{
			ompMessage->attributes[i+1].value.type = INT;
			ompMessage->attributes[i+1].value.intVal = pkt->getAttribute(i).intVal;
		} else
		if (pkt->getAttribute(i).type == FLOAT){
			// NON PREVISTO
		} else
		if (pkt->getAttribute(i).type == BOOL){
			// NON PREVISTO
		} else
		if (pkt->getAttribute(i).type == STRING){
			ompMessage->attributes[i+1].value.type = STRING;
			int k=0;
			while (pkt->getAttribute(i).stringVal[k] != '\0'){
				ompMessage->attributes[i+1].value.stringVal[k] = pkt->getAttribute(i).stringVal[k];
				k++;
			}
			ompMessage->attributes[i+1].value.stringVal[k] = '\0';
		}
	}
	cout << "Subscription manager: OCM: message translated." << endl;
	return ompMessage;
}




